home *** CD-ROM | disk | FTP | other *** search
/ 17 Bit Software 6: Level 6 / 17 Bit - Level 6 (1998)(Epic Marketing)[!].iso / quartz / q0429.dms / q0429.adf / libray / libobj / disc.c < prev    next >
C/C++ Source or Header  |  1991-08-08  |  4KB  |  215 lines

  1. /*
  2.  * disc.c
  3.  *
  4.  * Copyright (C) 1989, 1991, Craig E. Kolb
  5.  * All rights reserved.
  6.  *
  7.  * This software may be freely copied, modified, and redistributed
  8.  * provided that this copyright notice is preserved on all copies.
  9.  *
  10.  * You may not distribute this software, in whole or in part, as part of
  11.  * any commercial product without the express consent of the authors.
  12.  *
  13.  * There is no warranty or other guarantee of fitness of this software
  14.  * for any purpose.  It is provided solely "as is".
  15.  *
  16.  * $Id: disc.c,v 4.0 91/07/17 14:37:23 kolb Exp Locker: kolb $
  17.  *
  18.  * $Log:    disc.c,v $
  19.  * Revision 4.0  91/07/17  14:37:23  kolb
  20.  * Initial version.
  21.  * 
  22.  */
  23. #include "geom.h"
  24. #include "disc.h"
  25.  
  26. static Methods *iDiscMethods = NULL;
  27. static char discName[] = "disc";
  28.  
  29. unsigned long DiscTests, DiscHits;
  30.  
  31. Disc *
  32. DiscCreate(r, pos, norm)
  33. Float r;
  34. Vector *pos, *norm;
  35. {
  36.     Disc *disc;        /* Pointer to new disc. */
  37.  
  38.     if (r < EPSILON) {
  39.         RLerror(RL_WARN, "Degenerate disc.\n");
  40.             /*
  41.              * Don't create this primitive.
  42.              */
  43.             return (Disc *)NULL;
  44.     }
  45.  
  46.     if (VecNormalize(norm) == 0.) {
  47.         RLerror(RL_WARN, "Degenerate disc normal.\n");
  48.         return (Disc *)NULL;
  49.     }
  50.     /*
  51.      * Allocate new Disc.
  52.      */
  53.     disc = (Disc *)share_malloc(sizeof(Disc));
  54.     /*
  55.      * Initialize new disc.
  56.      * We store the square of the radius to save us a sqrt().
  57.      */
  58.     disc->radius = r*r;
  59.     disc->pos = *pos;
  60.     disc->norm = *norm;
  61.     /*
  62.      * Compute plane constant.
  63.      */
  64.     disc->d = dotp(pos, norm);
  65.     /*
  66.      * Allocate new primitive
  67.      */
  68.     return disc;
  69. }
  70.  
  71. Methods *
  72. DiscMethods()
  73. {
  74.     if (iDiscMethods == (Methods *)NULL) {
  75.         iDiscMethods = MethodsCreate();
  76.         iDiscMethods->name = DiscName;
  77.         iDiscMethods->create = (GeomCreateFunc *)DiscCreate;
  78.         iDiscMethods->methods = DiscMethods;
  79.         iDiscMethods->intersect = DiscIntersect;
  80.         iDiscMethods->normal = DiscNormal;
  81.         iDiscMethods->uv = DiscUV;
  82.         iDiscMethods->bounds = DiscBounds;
  83.         iDiscMethods->stats = DiscStats;
  84.         iDiscMethods->checkbounds = FALSE;
  85.         iDiscMethods->closed = FALSE;
  86.     }
  87.     return iDiscMethods;
  88. }
  89.  
  90. int
  91. DiscIntersect(disc, ray, mindist, maxdist)
  92. Disc *disc;
  93. Ray *ray;
  94. Float mindist, *maxdist;
  95. {
  96.     Vector hit;
  97.     Float denom, dist;
  98.  
  99.     DiscTests++;
  100.  
  101.     denom = dotp(&disc->norm, &ray->dir);
  102.     if (fabs(denom) < EPSILON)
  103.         /* Edge-on intersection */
  104.          return FALSE;
  105.  
  106.     dist = (disc->d - dotp(&disc->norm, &ray->pos)) / denom;
  107.     if (dist < mindist || dist > *maxdist)
  108.         /* Too close or too far */
  109.         return FALSE;
  110.     /*
  111.      *  Find difference between point of intersection and center of disc.
  112.      */
  113.     VecAddScaled(ray->pos, dist, ray->dir, &hit);
  114.     VecSub(hit, disc->pos, &hit);
  115.     /*
  116.      * If hit point is <= disc->radius from center, we've hit the disc.
  117.      */
  118.     if (dotp(&hit, &hit) <= disc->radius) {
  119.         *maxdist = dist;
  120.         DiscHits++;
  121.         return TRUE;
  122.     }
  123.     return FALSE;
  124. }
  125.  
  126. int
  127. DiscNormal(disc, pos, nrm, gnrm)
  128. Disc *disc;
  129. Vector *pos, *nrm, *gnrm;
  130. {
  131.     *gnrm = *nrm = disc->norm;
  132.     return FALSE;
  133. }
  134.  
  135. void
  136. DiscUV(disc, pos, norm, uv, dpdu, dpdv)
  137. Disc *disc;
  138. Vector *pos, *norm, *dpdu, *dpdv;
  139. Vec2d *uv;
  140. {
  141.     Float dist, val;
  142.  
  143.     dist =    (pos->x - disc->pos.x) * (pos->x - disc->pos.x) +
  144.         (pos->y - disc->pos.y) * (pos->y - disc->pos.y) +
  145.         (pos->z - disc->pos.z) * (pos->z - disc->pos.z);
  146.  
  147.     if (dist < EPSILON) {
  148.         uv->u = uv->v = 0.;
  149.         return;
  150.     }
  151.  
  152.     dist = sqrt(dist);
  153.     uv->v = dist / sqrt(disc->radius); /* should store r and r*r */
  154.  
  155.     val = pos->x / dist;
  156.  
  157.     if (fabs(val) > 1.)
  158.         uv->u = 0.5;
  159.     else {
  160.         uv->u = acos(val) / TWOPI; 
  161.         if (pos->y < 0.)
  162.             uv->u = 1. - uv->u;
  163.     }
  164.  
  165.     if (dpdu) {
  166.         VecSub(*pos, disc->pos, dpdv);
  167.         /* dpdu = dpdv X norm */
  168.         VecCross(dpdv, norm, dpdu);
  169.     }
  170. }
  171.  
  172. void
  173. DiscBounds(disc, bounds)
  174. Disc *disc;
  175. Float bounds[2][3];
  176. {
  177.     Float extent, rad;
  178.  
  179.     rad = sqrt(disc->radius);
  180.     /*
  181.      * Project disc along each of X, Y and Z axes.
  182.      */
  183.     extent = rad * sqrt(1. - disc->norm.x * disc->norm.x);
  184.     bounds[LOW][X] = disc->pos.x - extent;
  185.     bounds[HIGH][X] = disc->pos.x + extent;
  186.     extent = rad * sqrt(1. - disc->norm.y * disc->norm.y);
  187.     bounds[LOW][Y] = disc->pos.y - extent;
  188.     bounds[HIGH][Y] = disc->pos.y + extent;
  189.     extent = rad * sqrt(1. - disc->norm.z * disc->norm.z);
  190.     bounds[LOW][Z] = disc->pos.z - extent;
  191.     bounds[HIGH][Z] = disc->pos.z + extent;
  192. }
  193.  
  194. char *
  195. DiscName()
  196. {
  197.     return discName;
  198. }
  199.  
  200. void
  201. DiscStats(tests, hits)
  202. unsigned long *tests, *hits;
  203. {
  204.     *tests = DiscTests;
  205.     *hits = DiscHits;
  206. }
  207.  
  208. void
  209. DiscMethodRegister(meth)
  210. UserMethodType meth;
  211. {
  212.     if (iDiscMethods)
  213.         iDiscMethods->user = meth;
  214. }
  215.